package svc

import (
	"context"
	"fmt"
	_ "github.com/glebarez/go-sqlite"
	"github.com/zeromicro/go-zero/core/logx"
	"github.com/zeromicro/go-zero/core/stores/sqlx"
	"github.com/zeromicro/go-zero/rest"
	"os"
	"strings"
	"time"
	"yunzhan/api-server/internal/config"
	"yunzhan/api-server/internal/middleware"
	"yunzhan/api-server/internal/model"
)

type ServiceContext struct {
	Config             config.Config
	Conn               sqlx.SqlConn
	UserCorsMiddleware rest.Middleware
	AuditMiddleware    rest.Middleware
}

func NewServiceContext(c config.Config) *ServiceContext {
	var dbConn sqlx.SqlConn
	var dbType string

	if c.UseMysql {
		dbConn = sqlx.NewMysql(c.Mysql.DataSource)
		dbType = "mysql"
	} else {
		dbConn = sqlx.NewSqlConn("sqlite", c.SQLite.DataSource)
		dbType = "sqlite"
	}

	err := model.CreateTables(dbConn, dbType)

	if err != nil {
		logx.Errorf("元数据表初始化异常: %v", err)
		return nil
	}

	err = model.InitializeAdminUser(dbConn, dbType)
	if err != nil {
		logx.Errorf("超级管理员用户信息初始化异常: %v", err)
		return nil
	}

	sc := &ServiceContext{
		Config: c,
		Conn:   dbConn,
		UserCorsMiddleware: middleware.NewUserCorsMiddleware(
			"*",
			"Content-Type, Authorization",
			"GET, POST, PUT, DELETE, OPTIONS",
			"Content-Length, Content-Type",
			true,
		).Handle,
		AuditMiddleware: middleware.NewAuditMiddleware(dbConn, c).Handle,
	}

	// 启动心跳检查任务
	go sc.startHeartbeatCheckTask()

	return sc
}

func (sc *ServiceContext) insertComponentConfig() {
	// 读取 SQL 文件内容
	sqlFilePath := "etc/component_configs_data.sql"
	sqlContent, err := os.ReadFile(sqlFilePath)
	if err != nil {
		logx.Errorf("无法读取 SQL 文件: %v", err)
	}

	sqlStatements := strings.Split(string(sqlContent), ";")

	err = sc.Conn.Transact(func(session sqlx.Session) error {
		for _, stmt := range sqlStatements {
			stmt = strings.TrimSpace(stmt)
			if stmt == "" {
				continue
			}

			_, err := session.Exec(stmt)
			if err != nil {
				return fmt.Errorf("执行 SQL 语句失败: %v, error: %w", stmt, err)
			}
		}
		return nil
	})

	if err != nil {
		logx.Errorf("事务失败: %v", err)
	}

	logx.Infof("SQL文件执行成功")
}

func (sc *ServiceContext) startHeartbeatCheckTask() {
	ticker := time.NewTicker(10 * time.Second)
	defer ticker.Stop()

	for range ticker.C {
		sc.checkHeartbeats()
	}
}

func (sc *ServiceContext) checkHeartbeats() {
	cutoffTime := time.Now().Add(-30 * time.Second).Format("2006-01-02 15:04:05.000")

	var heartTable = sc.Config.SQLite.Tables.AgentHeartbeats

	if sc.Config.UseMysql {
		heartTable = sc.Config.Mysql.Tables.AgentHeartbeats
	}

	updateSQL := fmt.Sprintf(`
        UPDATE %s 
		SET status = false 
		WHERE last_heartbeat < ? AND status = true;`, heartTable)

	err := sc.Conn.TransactCtx(context.Background(), func(ctx context.Context, sess sqlx.Session) error {
		_, err := sess.ExecCtx(ctx, updateSQL, cutoffTime)
		if err != nil {
			return fmt.Errorf("failed to update heartbeat status: %w", err)
		}
		return nil
	})

	if err != nil {
		logx.Errorf("failed to check heartbeats: %v", err)
	}
}
